webpack 中 loader 和 plugin 的区别
loader
loader 加载器,webpack 原生只解析 js 文件,通过 loader 解析不同格式文件。 它作用是让 webpack 拥有解析加载非 js 文件的能力, 诸如编译、压缩等,最终一起打包到指定的文件中。
常见的 loader 有 babel-loader ES6 转化成 ES5 eslint-loader 通过 ESlint 检查 js tslint-loader 通过 TSLint 检查 js vue-loader 单文件方式窜写 Vue .vue sass-loader 解析 sass file-loader 文件解析成 url 路径是相对于原始文件资源,而非入口文件,根据配置将图片资源 copy 响应路径 url-loader 基于 file-loader 开发, 文件小的用 base64 替换 css-loader 解析 压缩 模块化 导入@imprt background(url) 语法 style-loader 把 css 注入到 js 中,通过 dom 操作 去加载 cache-loader 性能开销较大的 Loader 之前添加、目的是将结果缓存到磁盘里
plugin
plugin 是插件, 基于事件流框架 Tapable, 扩展 Webpack 功能。在 Webpack 运行的生命周期中会广播出许多事件, Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果
例如:打包之前删除原文件,打包结束后统计时长,打包后创建到到固定目录
add-asset-html-webpack-plugin 添加资源到 html compression-webpack-plugin gzip clean-webpack-plugin 删除文件 html-webpack-plugin:自动生成带入口的 index.html hard-source-webpack-plugin 二次缓存 speed-measure-webpack-plugin loader 速度分析, plugin loader 耗时 terser-webpack-plugin 压缩 js 支持压缩 ES6 webpack-bundle-analyzer 可视化输出文件体积
loader 实现
less-loader
// less-loader实现(经简化)
const less = require("less");
module.exports = function (content) {
const callback = this.async(); // 转译比较耗时,采用异步方式
const options = this.getOptions(); // 获取配置文件中less-loader的options
less.render(
content,
createOptions(options), // less转译的配置
(err, output) => {
callback(err, output.css); // 将生成的css代码传递给下一个loader
}
);
};
css-loader
- Css-loader 的作用主要是解析 css 文件中的@import 和 url 语句,处理 css-modules,并将结果作为一个 js 模块返回。
style-loader
// style-loader
import loaderUtils from "loader-utils";
module.exports = function (content) {
// do nothing
};
module.exports.pitch = function (remainingRequest) {
/*
* 用require语句获取css-loader返回的js模块的导出
* 用'!!'前缀跳过配置中的loader,避免重复执行
* 用remainingRequest参数获取loader链的剩余部分,在本例中是css-loader、less-loader
* 用loaderUtils的stringifyRequest方法将request语句中的绝对路径转为相对路径
*/
const requestPath = loaderUtils.stringifyRequest(
this,
"!!" + remainingRequest
);
// 本例中requestPath为:
// '!!../node_modules/css-loader/index.js!../node_modules/less-loader/dist/cjs.js!src/styles/index.less'
return `
const content = require(${requestPath})
const style = document.createElement('style');
style.innerHTML = content;
document.head.appendChild(style);
`;
};